'''
Created on May 13, 2012

@author: nicole
'''
from SimDisMeasurment import * 
from SimilarityEnum import *
from ReadWrite import *
from copy import *
from collections import defaultdict
from ThreadClass import ThreadClass



def lightkNNforSplit(firstid, lastid, data):
    
    nn_forallret = []
    
    for user in xrange(firstid, lastid):
        print(user)
        usersongs = data[user]

        nnlist = []

        for neighbor in xrange(0,len(data)):   
            neighborsongs = data[neighbor]
            distance = jaccardSimilaritylist(usersongs, neighborsongs)
            nnlist.append((neighbor, distance))        
        
        nn_forallret.append(sorted(nnlist, key = lambda a:a[1], reverse = True)[1:201])    
        
    return nn_forallret   











def kNN(datadict, measurment):
    nn_forall = defaultdict(list)
    datadict2 = datadict.copy()
    i = 0
    threads = []
    for u, user in datadict.iteritems():
        i = i+1
        del datadict2[u]
        #print threads
        '''
        if len(threads) >= 4:
            endedThread = threads[0]
            endedThread.join()
            threads = threads[1:4]
            partlist = endedThread.getList() 
            nnlist = nn_forall[u] + partlist
            nn_forall[u] = sorted(nnlist, key = lambda a:a[1], reverse = True)[1:10000]
            for neighbor, distance in partlist:
                #print(neighbor, distance)
                nn_forall[neighbor].append((u,distance))
        
        t = ThreadClass(datadict2, user, measurment)
        threads.append(t)
        t.start()
        '''
        
        nnlist=[]
        for neig, neighbor in datadict2.iteritems():
            
            if measurment == SimilarityEnum.Hamming:
                distance = hammingSimilarity(user, neighbor)
            elif measurment == SimilarityEnum.Cosine:
                distance = cosineSimilarity(user, neighbor)
            elif measurment == SimilarityEnum.Jaccard:
                distance = jaccardSimilarity(user, neighbor)
            
            #print(distance)
            nnlist.append((neig, distance))

        for neighbor, distance in nnlist:
            nn_forall[neighbor].append((u,distance))
        
        nn_forall[u] = sorted(nnlist, key = lambda a:a[1], reverse = True)[0:200]

        
        print(i)
    return nn_forall
            



def kNNforSplit(firstid, lastid, data):
    
    nn_forall = [[] for k in range(0,len(data))]
    
    for user in range(firstid, lastid):
        print(user)
        usersongs = data[user]
        nnlist = nn_forall[user]
        
        for neighbor in range(0,firstid):   
            neighborsongs = data[neighbor]
            distance = jaccardSimilaritylist(usersongs, neighborsongs)
            nnlist.append((neighbor, distance))        
            
        for neighbor in range(user+1,len(data)):   
            neighborsongs = data[neighbor]
            distance = jaccardSimilaritylist(usersongs, neighborsongs)
            nnlist.append((neighbor, distance))
        
        for neighbor, distance in nnlist:
            nn_forall[neighbor].append((user,distance))
        
    nn_forallret = []   
    for user in range(firstid, lastid):
        nn_forallret.append(sorted(nn_forall[user], key = lambda a:a[1], reverse = True)[0:200])
    return nn_forallret   